Python之路 - 函数进阶
嵌套函数 🍀
嵌套函数即函数里面再套一个函数 , 如下 :
1 | # 全局变量name |
嵌套函数不能越级调用 , 也就是说我们不能在func2
的外部去调用func3
, 当然反过来我们的代码就进入无限递归了
当然我们有时需要的就是在嵌套函数中 , 使用上一层的变量 , 那么我们可以使用nonlocal
语句
nonlocal
的作用就是改变变量的作用域 , 但是不会扩展到全局变量 , 即只能在函数内部改变 ; nonlocal声明之后 , 会从上层开始找并返回第一个变量,如果有修改变量,则会影响到引用层以及子层的值.
1 | #下面例子.表面nonlocal声明变量n后,对n的修改会影响到最外层的func函数声明的变量n的值 |
高阶函数 🍀
高阶函数就是将一个函数以参数的形式传入另一个函数
1 | # 定义一个主函数,并设置一个参数func |
闭包 🍀
闭包必须是内部定义的函数 (嵌套函数) , 该函数包含对外部作用域而不是全局作用域名字的引用
1 | def foo(): |
在嵌套函数中 , 我们可以将函数作为参数 (高阶函数) 或者返回值进行传递 , 函数作为一个值可以赋给变量 , 如下 :
1 | def decorator(func): |
所以利用闭包我们可以实现两种需求 :
- 在不修改源代码的情况下给函数增加功能
- 为某个函数的参数进行提前赋值
添加功能 🍀
如果我们以相同的变量名去覆盖函数名 , 修改上述代码 , 如下 :
1 | def decorator(func): |
通过定义了变量decorator
, 使其原来的函数decorator()
被覆盖 , 也就是说我们实现了在不修改func()
函数的情况下 , 为func()
函数新添加了一个功能 , 当然上述例子中的功能仅仅是打印一句 “I am decorator”
当然我们还可以这样 :
1 | def func(): |
闭包方式加参数版 :
1 | def decorator(func): |
数据存储 🍀
1 | def func(): |
一道面试题的翻译版本
1 | def func(): |
面试题原版
1 | # 知识点:列表生成式,匿名函数,闭包 |
对于闭包 , 我们可以使用__closure__
属性查看闭包函数中引用变量的取值 , __closure__
里包含了一个元组 , 这个元组中的每个元素是cell
类型的对象 , 默认为None
1 | def func(): |
装饰器 🍀
装饰器即给原来的函数进行装饰的工具
装饰器由函数去生成 , 用于装饰某个函数或者方法 (类中的说法) , 它可以让这个函数在执行之前或者执行之后做某些操作
装饰器其实就是上一节闭包中的添加功能实现 , 不过使用闭包太过麻烦 , 所以Python就创造出一个语法糖来方便我们使用
语法糖 : 指那些没有给计算机语言添加新功能 , 而只是对人类来说更”甜蜜”的语法 , 语法糖主要是为程序员提供更实用的编码方式 , 提高代码的可读性 , 并有益于更好的编码风格
语法糖如下 :
1 | # 装饰器函数 |
该语法糖只是将我们闭包中最后自己处理的部分进行处理了 , 如下 :
1 |
|
另一种一般不使用的方式 :
1 | # 装饰器函数 |
实例
1 | def decorator(func): |
多个装饰器装饰同一个函数
1 | def decorator1(func): |
被装饰函数带有参数
1 | def decorator(func): |
带参数的装饰器
1 | F = False |
我们利用装饰器虽然功能达到了 , 但是注意原函数的元信息却没有赋值到装饰器函数内部 , 比如函数的注释信息 , 如果我们需要将元信息也赋值到装饰器函数内部 , 可以使用functools模块中的wraps()
方法 , 如下 :
1 | import functools |
多个装饰器,装饰一个函数
1 | def wrapper1(f): #这里接收的参数是inner2 |
此外,还可以通过以下这个例子还学习闭包和装饰器.
需求1.测试func1函数的执行时间
1 | import time |
需求2.测试func1,func2这2个函数的执行时间
1 | import time |
需求3.不能修改func1,func2函数本身,也不能修改调用方式
1 | import time |
需求4.精简代码.使用语法糖格式.这个语法糖格式就是装饰器.其中timer函数就是装饰函数
1 | import time |
需求5.给装饰器传递参数
1 | import time |